package operations;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


import util.Randomness;
import model.CUT;
import model.ConstructorDeclared;
import model.TestClusterBuilder;
import model.StatementKind;
public class CreateObject extends Operation implements Cloneable{

	private  String ref;
	private final StatementKind constructor;
	private final List<Object> values;


	public CreateObject(String ref, StatementKind constructor, List<Object>  values) {
		this.ref = ref;
		this.constructor = constructor;
		this.values = values;
	}
	public List<Object> getValues(){
		 return this.values;	 
	 }
	public String getRef(){
		 return this.ref;	 
	 }
	public void setRefrence(String ref){
		  this.ref=ref;	 
	 }
	
	 public void setValues(List<Object> newValues){
		  this.values.clear();
		  this.values.addAll(newValues);
	 }


	public static CreateObject generate(CUT clazz, TestClusterBuilder TestCluster){
//		if(clazz.getClazz().getName().equals("java.util.Locale"))
//			System.out.println("InvokeMethod: "+clazz.getClazz() );

		Map<String, String[]> refFactory = TestCluster.getRefFactory();

		if(clazz.getConstructors().length==0) return null;
		StatementKind constructor = clazz.getConstructors()[Randomness.nextRandomInt(clazz.getConstructors().length)];
		List<Object> values=Operation.selectInputs(constructor,TestCluster);
		String ref = getReference(clazz.getClazz().getName(),refFactory);

		return new CreateObject(ref,constructor,values);
	}
	public static CreateObject recommendedgenerate(Class<?> clz,StatementKind constr, TestClusterBuilder TestCluster){
		if(!(constr instanceof ConstructorDeclared)) return null;
		
		StatementKind constructor =constr;// clazz.getConstructors()[Randomness.nextRandomInt(clazz.getConstructors().length)];
		List<Object> values=Operation.selectInputs(constructor,TestCluster);
		
		Map<String, String[]> refFactory = TestCluster.getRefFactory();
		String ref = getReference(clz.getName(),refFactory);

		return new CreateObject(ref,constructor,values);
	}
	
	public StatementKind getConstructor(){
		return this.constructor;
	}
 @Override
	public CreateObject clone() {
		List<Object> cloneValues = new ArrayList<Object>(values);
		final CreateObject clone = new CreateObject(ref,constructor,cloneValues);
		return clone;
	}
	@Override
	public String toString() {
	     StringBuilder sb = new StringBuilder();
	     StatementKind CUT =this.constructor;
    	 sb.append(" "+this.ref + " = new ");
	     	
	     sb.append(((ConstructorDeclared) CUT).getConstructor().getName() +"(");
	     List<Object> values = this.getValues();
	     List<Class<?>> inputType =((ConstructorDeclared) CUT).getInputTypes();
	     for(int j=0;j<values.size();j++){
	    	 Class<?> valueClass=inputType.get(j);
	    	 Object value=values.get(j);
	    	 sb.append(ValuesGenerator.toCodeString(valueClass,value));
	         if (j < (values.size() - 1))
	           sb.append(",");
	       }

	     sb.append(");");   
	     return sb.toString();

	}

}